package com.wzy.oa_sys.service.impl.attendance;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzy.oa_sys.mapper.attendance.AttendanceMapper;
import com.wzy.oa_sys.mapper.attendance.TimeStandardMapper;
import com.wzy.oa_sys.mapper.report.WorkMapper;
import com.wzy.oa_sys.mapper.user.UserMapper;
import com.wzy.oa_sys.model.pojo.attendance.OaAttendance;
import com.wzy.oa_sys.model.pojo.attendance.OaTimeStandards;
import com.wzy.oa_sys.model.pojo.report.OaWork;
import com.wzy.oa_sys.model.pojo.user.OaUser;
import com.wzy.oa_sys.model.request.attendance.AttendanceReq;
import com.wzy.oa_sys.model.response.attendance.AttendanceResp;
import com.wzy.oa_sys.model.response.attendance.VacationResp;
import com.wzy.oa_sys.service.attendance.AttendanceService;
import com.wzy.oa_sys.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.sql.Time;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AttendanceServiceImpl extends ServiceImpl<AttendanceMapper, OaAttendance> implements AttendanceService {


    @Autowired
    private AttendanceMapper attendanceMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TimeStandardMapper timeStandardMapper;
    @Autowired
    private WorkMapper workMapper;
    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public List<AttendanceResp> getAttendanceList(HttpServletRequest request) {
        Long userId = jwtUtil.extractUserId(request);
        String role = jwtUtil.extractUserRole(request);
        List<OaAttendance> oaAttendances = attendanceMapper.selectList(null);
        oaAttendances.sort((o1, o2) -> o2.getDtTime().compareTo(o1.getDtTime()));
        List<AttendanceResp> attendanceResps = new ArrayList<>();
        oaAttendances.forEach(oaAttendance -> {
            attendanceResps.add(AttendanceResp.builder()
                    .type(oaAttendance.getCType())
                    .name(userMapper.selectUserById(oaAttendance.getNUserId()).getCRealName())
                    .time(oaAttendance.getDtTime().toString().replace("T", " "))
                    .notes(oaAttendance.getCNotes())
                    .userId(oaAttendance.getNUserId())
                    .state(oaAttendance.getCState()).build());
        });
        if(role.contains("SUPERMAN")){
            return attendanceResps;
        }else{
            List<AttendanceResp> attendanceRespList = new ArrayList<>();
            if(userMapper.selectUserById(userId)!=null){
                long nDeptId = userMapper.selectUserById(userId).getNDeptId();
                QueryWrapper<OaUser> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("n_dept_id", nDeptId);
                List<OaUser> oaUsers = userMapper.selectList(queryWrapper);
                HashSet<Long> userIds = new HashSet<>();
                oaUsers.forEach(oaUser -> {
                    userIds.add(oaUser.getNUserId());
                });
                attendanceResps.forEach(attendanceResp -> {
                    if(userIds.contains(attendanceResp.getUserId())){
                        attendanceRespList.add(attendanceResp);
                    }
                });
                return attendanceRespList;
            }
        }
        return attendanceResps;
    }

    @Override
    public void addAttendance(AttendanceReq attendanceReq) {
        OaAttendance oaAttendance = new OaAttendance();
        oaAttendance.setCType(attendanceReq.getType());
        LocalDateTime now = LocalDateTime.now();
        oaAttendance.setDtTime(now);
        oaAttendance.setNUserId(attendanceReq.getName());
        oaAttendance.setCNotes(attendanceReq.getNotes());
        //上班标准时间信息
        QueryWrapper<OaTimeStandards> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("c_type","上班");
        OaTimeStandards goWork = timeStandardMapper.selectOne(queryWrapper);
        //下班标准时间信息
        QueryWrapper<OaTimeStandards> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("c_type","下班");
        OaTimeStandards afterWork = timeStandardMapper.selectOne(queryWrapper2);
        //查看今天是否已经打卡,查从今天0点开始到24点结束的记录
        QueryWrapper<OaAttendance> queryWrapper3 = new QueryWrapper<>();
        queryWrapper3.eq("n_user_id",attendanceReq.getName());
        queryWrapper3.between("dt_time",now.withHour(0).withMinute(0).withSecond(0),now.withHour(23).withMinute(59).withSecond(59));
        queryWrapper3.eq("c_type",attendanceReq.getType());
        List<OaAttendance> oaAttendances = attendanceMapper.selectList(queryWrapper3);
        if(oaAttendances.size()>0){
            throw new RuntimeException("今天已经打卡："+oaAttendance.getCType());
        }
        if(oaAttendance.getCType().equals("上班")){
            if(goWork!=null){
                //上班标准时间
                Time dtTime = goWork.getDtTime();
                //当前时间
                LocalTime localTime = now.toLocalTime();
                Time nowTime = Time.valueOf(localTime);
                //判断是否迟到
                if(nowTime.after(dtTime)){
                    oaAttendance.setCState("迟到");
                }else{
                    oaAttendance.setCState("正常");
                }
                }
        }else if(oaAttendance.getCType().equals("下班")){
            if(afterWork!=null){
                //下班标准时间
                Time dtTime = afterWork.getDtTime();
                //当前时间
                LocalTime localTime = now.toLocalTime();
                Time nowTime = Time.valueOf(localTime);
                //判断是否早退
                if(nowTime.before(dtTime)){
                    oaAttendance.setCState("早退");
                }else{
                    oaAttendance.setCState("正常");
                }


            }
        }
        attendanceMapper.insert(oaAttendance);
        if(oaAttendance.getCType().equals("下班")){
            //查看是否有该用户的工作时间信息
            QueryWrapper<OaWork> oaWorkQueryWrapper = new QueryWrapper<>();
            oaWorkQueryWrapper.eq("n_user_id",attendanceReq.getName());
            //存在，则更新工作时间
            if(workMapper.selectOne(oaWorkQueryWrapper)!=null){
                OaWork oaWork = workMapper.selectOne(oaWorkQueryWrapper);
                QueryWrapper<OaAttendance> oaAttendanceQueryWrapper = new QueryWrapper<>();
                oaAttendanceQueryWrapper.eq("n_user_id",attendanceReq.getName());
                List<OaAttendance> oaAttendances1 = attendanceMapper.selectList(oaAttendanceQueryWrapper);
                //上班打卡信息
                List<OaAttendance> toWork = oaAttendances1.stream().filter(oaAttendance1 -> oaAttendance1.getCType().equals("上班"))//上班打卡信息
                        .sorted(Comparator.comparing(OaAttendance::getDtTime))//从小到大排序
                        .collect(Collectors.toList());
                OaAttendance oaAttendance1 = toWork.get(toWork.size()-1);
                System.out.println("上班"+oaAttendance1);
                //下班打卡信息
                List<OaAttendance> workOut = oaAttendances1.stream().filter(oaAttendance2 -> oaAttendance2.getCType().equals("下班"))//上班打卡信息
                        .sorted(Comparator.comparing(OaAttendance::getDtTime))//从小到大排序
                        .collect(Collectors.toList());
                OaAttendance oaAttendance2 = workOut.get(toWork.size()-1);
                System.out.println("下班"+oaAttendance2);
                // 计算时间差
                long hoursDifference = ChronoUnit.HOURS.between(oaAttendance1.getDtTime(), oaAttendance2.getDtTime());
                long minutesDifference = ChronoUnit.MINUTES.between(oaAttendance1.getDtTime(), oaAttendance2.getDtTime()) % 60;
                //转为小时
                double hoursAsDouble = hoursDifference + (minutesDifference / 60.0);
                hoursAsDouble = Math.round(hoursAsDouble * 100.0) / 100.0;
                //更新oaWork表
                oaWork.setCWorkTime(hoursAsDouble+ oaWork.getCWorkTime());
                workMapper.update(oaWork,oaWorkQueryWrapper);
                System.out.println("当前工作时间（小时）: " + oaWork.getCWorkTime());
                //不存在则新增该用户的工作时间
            }else{
                OaWork oaWork = new OaWork();
                oaWork.setNUserId(attendanceReq.getName());
                QueryWrapper<OaAttendance> oaAttendanceQueryWrapper = new QueryWrapper<>();
                oaAttendanceQueryWrapper.eq("n_user_id",attendanceReq.getName());
                oaAttendanceQueryWrapper.eq("c_type","上班");
                OaAttendance oaAttendance1 = attendanceMapper.selectOne(oaAttendanceQueryWrapper);
                //获取时间差
                long hoursDifference = ChronoUnit.HOURS.between(oaAttendance1.getDtTime(), now);
                long minutesDifference = ChronoUnit.MINUTES.between(oaAttendance1.getDtTime(), now) % 60;
                //转为小时
                double hoursAsDouble = hoursDifference + (minutesDifference / 60.0);
                hoursAsDouble = Math.round(hoursAsDouble * 100.0) / 100.0;
                oaWork.setCWorkTime(hoursAsDouble);
                int insert = workMapper.insert(oaWork);
                System.out.println(insert);
                System.out.println("当前工作时间（小时）: " + oaWork.getCWorkTime());
            }
        }
    }

    @Override
    public List<AttendanceResp> getTodayVacationList(Long userId) {
        //查看今天是否已经打卡,查从今天0点开始到24点结束的记录
        QueryWrapper<OaAttendance> queryWrapper3 = new QueryWrapper<>();
        queryWrapper3.eq("n_user_id",userId);
        LocalDateTime now = LocalDateTime.now();
        queryWrapper3.between("dt_time",now.withHour(0).withMinute(0).withSecond(0),now.withHour(23).withMinute(59).withSecond(59));
        List<OaAttendance> oaAttendances = attendanceMapper.selectList(queryWrapper3);
        List<AttendanceResp> attendanceResps = new ArrayList<>();
        oaAttendances.forEach(oaAttendance -> {
            AttendanceResp attendanceResp = AttendanceResp.builder()
                    .type(oaAttendance.getCType())
                    .time(oaAttendance.getDtTime().toString().replace("T", " "))
                    .state(oaAttendance.getCState()).build();
            attendanceResps.add(attendanceResp);
        });
        return attendanceResps;
    }


}





